﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
using NetworkAssetManager.Entity;
using System.Management;
using log4net; 
namespace NetworkAssetManager.WMI
{
    class RegistryHelper
    {
        private static readonly ILog _logger = LogManager.GetLogger(typeof(RegistryHelper));

        public static List<EntSoftwares> GetInstalledSoftwareDetails(ManagementScope scope)
        {
            _logger.Info("Collecting software installed details for machine " + scope.Path.Server);

            List<EntSoftwares> lstSoftwares = new List<EntSoftwares>();
            ManagementPath mypath = new ManagementPath("StdRegProv");
            const uint HKEY_LOCAL_MACHINE = unchecked((uint)0x80000002);
            ManagementClass wmiRegistry = new ManagementClass(scope, mypath, null);
            string keyPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
            object[] methodArgs = new object[] { HKEY_LOCAL_MACHINE, keyPath, null };
            uint returnValue = (uint)wmiRegistry.InvokeMethod("EnumKey", methodArgs);

            try
            {
                if (null != methodArgs[2])
                {

                    string[] subKeys = methodArgs[2] as String[];

                    if (subKeys == null)
                        return lstSoftwares;

                    ManagementBaseObject inParam =
                    wmiRegistry.GetMethodParameters("GetStringValue");

                    inParam["hDefKey"] = HKEY_LOCAL_MACHINE;

                    string keyName = "";

                    ManagementBaseObject outParam = null;
                    foreach (string subKey in subKeys)
                    {

                        keyPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" + subKey;

                        keyName = "DisplayName";
                        inParam["sSubKeyName"] = keyPath;
                        inParam["sValueName"] = keyName;
                        outParam = wmiRegistry.InvokeMethod("GetStringValue", inParam, null);
                        if (outParam != null && (uint)outParam["ReturnValue"] == 0)
                        {
                            EntSoftwares objEntSoftwares = new EntSoftwares();
                            objEntSoftwares.Name = outParam["sValue"].ToString();

                            keyName = "DisplayVersion";
                            inParam["sSubKeyName"] = keyPath;
                            inParam["sValueName"] = keyName;
                            outParam = wmiRegistry.InvokeMethod("GetStringValue", inParam, null);
                            if ((uint)outParam["ReturnValue"] == 0)
                            {
                                objEntSoftwares.Version = outParam["sValue"].ToString();
                            }
                            else
                            {
                                objEntSoftwares.Version = "";
                            }

                            keyName = "InstallLocation";
                            inParam["sSubKeyName"] = keyPath;
                            inParam["sValueName"] = keyName;
                            outParam = wmiRegistry.InvokeMethod("GetStringValue", inParam, null);
                            if ((uint)outParam["ReturnValue"] == 0)
                            {
                                objEntSoftwares.Location = outParam["sValue"].ToString();
                            }
                            else
                            {
                                objEntSoftwares.Location = "";
                            }


                            keyName = "InstallDate";
                            inParam["sSubKeyName"] = keyPath;
                            inParam["sValueName"] = keyName;
                            outParam = wmiRegistry.InvokeMethod("GetStringValue", inParam, null);
                            if ((uint)outParam["ReturnValue"] == 0)
                            {
                                objEntSoftwares.InstallDate = WMIUtil.ToShortDateTime(outParam["sValue"].ToString());
                            }
                            else
                            {
                                objEntSoftwares.InstallDate = DateTime.MinValue;
                            }

                            lstSoftwares.Add(objEntSoftwares);
                        }
                    }
                }
            }
            catch (System.Exception e)
            {
                _logger.Error("Exception in installed software collection " + e.Message);
            }
            return lstSoftwares; 
        }
    }
}
